#include "QuadTree.h"
#include "../Colide/Colide.h"
#include <SDL2/SDL2_gfxPrimitives.h>
#include <algorithm>



void QuadTree::insert(Object* o)
{
	if (!boundary.contains(o->getRect()))return;
	if (!devided)
	{
		if (objs.size() < max_ObjectCount || depth >= max_Depth)
		{ 
			if(std::find(objs.begin(), objs.end(), o) == objs.end())objs.push_back(o);

			

		}
		else {
			subdevide();
			ne->insert(o);
			nw->insert(o);
			se->insert(o);
			sw->insert(o);

			for (Object* obj : objs)
			{
				ne->insert(obj);
				nw->insert(obj);
				se->insert(obj);
				sw->insert(obj);
			}
			objs.clear();
		}
		return;
	}
	else 
	{
		ne->insert(o);
		nw->insert(o);
		se->insert(o);
		sw->insert(o);
		return;
	}
}

void QuadTree::subdevide()
{
	auto minpoint = boundary.min;
	auto maxpoint = boundary.max;

	ne = new QuadTree;
	ne->boundary = Rect(vec2(maxpoint + minpoint) / 2.0f, maxpoint);

	ne->root = this;
	ne->world = world;


	ne->depth = depth + 1;

	nw = new QuadTree;
	nw->boundary = Rect(vec2(minpoint.x, (maxpoint.y + minpoint.y) / 2), vec2((maxpoint.x + minpoint.x) / 2, maxpoint.y));

	nw->root = this;
	nw->world = world;


	nw->depth = depth + 1;

	sw = new QuadTree;
	sw->boundary = Rect(minpoint, (maxpoint + minpoint) / 2.0f);

	sw->root = this;
	sw->world = world;

	sw->depth = depth + 1;

	se = new QuadTree;
	se->boundary = Rect(vec2((maxpoint.x+minpoint.x)/2,minpoint.y),vec2(maxpoint.x,(maxpoint.y+minpoint.y)/2));

	se->root = this;
	se->world = world;



	se->depth = depth + 1;

	devided = true;
}

void QuadTree::merge()
{
	if (!devided)
	{
		for (auto o : objs)
		{
			root->objs.push_back(o);
		}
		objs.clear();

	}
	else
	{
		ne->merge();
		delete ne;
		nw->merge();
		delete nw;
		se->merge();
		delete se;
		sw->merge();
		delete sw;
		
	}
    devided = false;
}

void QuadTree::remove(Object* o)
{
	
	if (!devided)
	{
		if (std::find(objs.begin(), objs.end(), o) != objs.end())
		{
			objs.erase(std::find(objs.begin(), objs.end(), o));
			
		}
		else return;
	}
	else {
		ne->remove(o);
		nw->remove(o);
		se->remove(o);
		sw->remove(o);
	}
}

void QuadTree::update()
{
  rectangleColor(world->renderer,boundary.min.x,boundary.min.y,boundary.max.x,boundary.max.y,0x0000FFFF);
	

	
	if (!devided)
	{
		
		if (objs.size() == 2)
		{
			world->addColideInfo(objs[0], objs[1]);
			
		}
		else if (objs.size() > 2)
		{
			for (int i = 0; i < objs.size(); i++)
			{
				for (int j = i + 1; j < objs.size(); j++)
				{
					world->addColideInfo(objs[i], objs[j]);
				}
			}
		}
		else
		{
			return;
		}
	}
	else
	{
		if (!ne->devided)
		{
			auto o=getObjs();
			for (int i = 0; i < o.size(); i++)
			{
				for (int j = i + 1; j < o.size(); j++)
				{
					world->addColideInfo(o[i], o[j]);
				}
			}
		}
		


		ne->update();
		nw->update();
		se->update();
		sw->update();


		

		
	}
	
}


std::vector<Object*> QuadTree::getObjs() {
	 return objs;
}










